package org.xx.armory.swing.components;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static java.util.Arrays.asList;
import static org.xx.armory.commons.Validators.notEmpty;
import static org.xx.armory.commons.Validators.notNull;

/**
 * 格式化工具类。
 *
 * TODO: 根据当前地区设置各个类型的显示样式。
 */
public class FormatUtils {
    private volatile static Locale locale;

    public static void setLocale(
            Locale locale
    ) {
        FormatUtils.locale = notNull(locale, "locale");
    }

    public static Locale getLocale() {
        return locale;
    }

    public static NumberFormat getNumberTextFormat() {
        return new DecimalFormat("#0");
    }

    public static NumberFormat getNumberFormat() {
        return new DecimalFormat("#,##0");
    }

    public static NumberFormat getFloatFormat() {
        return new DecimalFormat("#,##0.00");
    }

    public static NumberFormat getCurrencyFormat() {
        return new DecimalFormat("#,##0.00");
    }

    public static NumberFormat getPercentFormat() {
        return new DecimalFormat("#,##0.00%");
    }

    public static DateFormat getDateFormat() {
        return new CompositeDateFormat("yyyy/MM/dd", "yyyyMMdd", "yyyy/MM", "yyyMM", "yyyy");
    }

    public static DateFormat getDateTimeFormat() {
        return new CompositeDateFormat("yyyy/MM/dd HH:mm:ss", "yyyyMMdd HHmmss");
    }

    private static class CompositeDateFormat
            extends DateFormat {
        private final List<DateFormat> children;

        public CompositeDateFormat(
                DateFormat... formats
        ) {
            notEmpty(formats, "formats");

            this.children = new ArrayList<>(asList(formats));
        }

        public CompositeDateFormat(
                String... formats
        ) {
            notEmpty(formats, "formats");

            final List<DateFormat> list = new ArrayList<>(formats.length);
            for (String format : formats) {
                list.add(new SimpleDateFormat(format));
            }

            this.children = list;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public StringBuffer format(
                Date date,
                StringBuffer toAppendTo,
                FieldPosition fieldPosition
        ) {
            if (this.children.isEmpty()) {
                throw new IllegalStateException("children is empty");
            }

            return this.children.get(0).format(date, toAppendTo, fieldPosition);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Date parse(
                String source,
                ParsePosition pos
        ) {
            if (this.children.isEmpty()) {
                throw new IllegalStateException("children is empty");
            }

            for (final DateFormat child : this.children) {
                final Date result = child.parse(source, pos);
                if (result != null) {
                    return result;
                }
            }

            return null;
        }
    }
}
